import os
import requests
import concurrent.futures
from urllib.parse import urljoin
import subprocess


def download_m3u8_video(m3u8_url, output_file="output.mp4", max_workers=5):
    # 1. 下载m3u8文件
    print(f"正在下载m3u8文件: {m3u8_url}")
    response = requests.get(m3u8_url)
    response.raise_for_status()                         # 判断请求是否成功
    m3u8_content = response.text

    # 2. 解析ts片段URL
    base_url = m3u8_url.rsplit('/', 1)[0] + '/'
    ts_urls = []

    for line in m3u8_content.split('\n'):
        if line.endswith('.ts'):
            ts_url = urljoin(base_url, line)
            ts_urls.append(ts_url)

    print(f"找到 {len(ts_urls)} 个ts片段")

    # 3. 创建临时目录
    temp_dir = "temp_ts_files"
    os.makedirs(temp_dir, exist_ok=True)

    # 4. 下载所有ts片段（多线程）
    def download_ts(ts_url, index):
        try:
            ts_response = requests.get(ts_url, timeout=30)
            ts_response.raise_for_status()
            ts_path = os.path.join(temp_dir, f"{index:04d}.ts")
            with open(ts_path, 'wb') as f:
                f.write(ts_response.content)
            return ts_path
        except Exception as e:
            print(f"下载失败 {ts_url}: {str(e)}")
            return None

    print("开始下载ts片段...")
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = [executor.submit(download_ts, url, i) for i, url in enumerate(ts_urls)]
        ts_files = [future.result() for future in concurrent.futures.as_completed(futures)]

    ts_files = [f for f in ts_files if f is not None]
    print(f"成功下载 {len(ts_files)} 个ts片段")

    # 5. 合并视频（使用ffmpeg）
    print("开始合并视频...")
    file_list_path = os.path.join(temp_dir, "filelist.txt")

    # 创建文件列表
    with open(file_list_path, 'w') as f:
        for ts_file in sorted(ts_files):
            f.write(f"file '{os.path.basename(ts_file)}'\n")

    # 使用ffmpeg合并
    cmd = [
        'ffmpeg',  # 1. 调用FFmpeg可执行文件（需已安装并配置环境变量）
        '-f', 'concat',  # 2. 指定输入格式为concat（用于合并多个媒体文件）
        '-safe', '0',  # 3. 禁用安全检查（允许使用绝对路径/特殊字符路径）
        '-i', file_list_path,  # 4. 指定输入文件（包含待合并文件列表的文本文件）
        '-c', 'copy',  # 5. 使用流拷贝模式（不重新编码，直接复制音视频流）
        output_file  # 6. 指定输出文件路径（合并后的最终文件）
    ]

    try:
        subprocess.run(cmd, check=True, cwd=temp_dir)
        print(f"视频合并完成: {output_file}")
    except subprocess.CalledProcessError as e:
        print(f"合并失败: {str(e)}")
    finally:
        # 清理临时文件
        print("清理临时文件...")
        for ts_file in ts_files:
            os.remove(ts_file)
        os.remove(file_list_path)
        os.rmdir(temp_dir)


# 使用示例
if __name__ == "__main__":
    m3u8_url = "https://m3u8.girigirilove.com/zijian/oldanime/2025/07/cht/9nineShihaishanoOukanCHT/01/playlist.m3u8"
    download_m3u8_video(m3u8_url, output_file="9nine_Shihaishano_Oukan_CHT_01.mp4")
